#ifndef __MVT_SEVT_H__
#define __MVT_SEVT_H__

#include "mvdef.h"

MVCXX_EXTERN_BEGIN

#define EVT_DEFAULT_QINT_MS 100 ///< 默认轮询周期100ms
#define EVT_DEFAULT_PRIO    128 ///< 默认优先级

typedef enum _event_flag
{
    EVT_INVALID         = 0,
    EVT_NORMAL          = 1,  ///< 普通（添加）
    EVT_CONFLICT_DROP   = 2,  ///< 冲突检查（已存在则丢弃）
    EVT_CONFLICT_MODIFY = 3,  ///< 冲突检查（已存在则替换）
    EVT_DROP            = 4,  ///< 丢弃
}evt_flag_e;

typedef enum _event_call_status
{
    EVT_CALLS_NORMAL   = 0,  ///< 普通触发
    EVT_CALLS_TIMEOUT  = 1,  ///< 超时触发
}evt_calls_e;

/**
 * @brief 定时事件触发回调
 * 
 * @param p_evt_data [in] 扩展内存块数据
 * @param s32_len    [in] 扩展内存块数据长度
 * @param p_usr_data [in] 地址传递类数据
 * @param u8_status  [in] 事件的触发状态[evt_calls_e]
 * 
 * @return 后续操作指示
 *  > 0 : 变更下次触发间隔（成为循环触发事件）
 *  = 0 : 按照原有设定下次触发或终止
 *  MV_EC_ABORT: 强制终止
 */
typedef mv_s32_t(*pf_on_event_occur)(mv_vptr_t p_evt_data, mv_s32_t s32_len, mv_vptr_t p_usr_data, mv_u8_t u8_status);

/**
 * @brief 定时事件释放回调
 * 
 * @param p_evt_data [in] 扩展内存块数据
 * @param s32_len    [in] 扩展内存块数据长度
 * @param p_usr_data [in] 地址传递类数据
 * 
 * @return \
 * @note 用于给用户层释放自己额外申请的资源，避免事件自动销毁时，该部分内存没有被处理的问题
 */
typedef mv_void_t(*pf_on_event_release)(mv_vptr_t p_evt_data, mv_s32_t s32_len, mv_vptr_t p_usr_data);

typedef struct _event_item
{
    /** internal  data */
    struct _event_item *next;              ///< EVT模块采用链表方式，此参数内部使用，切勿赋值！
    mv_bool_t           bl_oncall;         ///< EVT模块内部标记当前事件是否处理中
    mv_u8_t             au8_intreserved[3];///< （内部数据对齐保留）
    mv_time_t           ts_next_call;      ///< EVT模块内部唤起事件的时间点换算
    /** userspace data */
    mv_v8_t             av8_name[16];      ///< 事件名称（EVT模块采用名称驱动，不同的事件请使用不同名称以便区分）
    mv_u8_t             u8_evt_flag;       ///< 事件标识[evt_flag_e]
    mv_u8_t             u8_priority;       ///< 优先级[1,255];值越大越优先级越高(0为默认优先级)
    mv_u8_t             au8_reserved[2];   ///< （用户数据对齐保留）
    pf_on_event_occur   f_on_evt;          ///< 事件执行回调
    pf_on_event_release f_on_release;      ///< 事件用户资源释放回调
    mv_u32_t            u32_interval_ms;   ///< 循环事件时间间隔（毫秒）；与"u32_drop_pass_ms"互斥优先
    mv_u32_t            u32_drop_pass_ms;  ///< 事件超时执行限制（毫秒，由于优先级翻转等资源调度原因导致的时间过期执行的最大容忍时间）
    mv_s32_t            s32_data_len;      ///< 事件参数长度
    mv_vptr_t           p_usr_data;        ///< 无额外内存申请的持久变量使用，用于指向持续有效参数的事件
    mv_u8_t             au8_evt_data[1];   ///< 1长数组扩展内存块申请区，用于缓存临时参数构成的事件
}evt_item_t;

typedef struct _event_handle
{
    mv_v8_t   av8_evt_prefix[8];           ///< 定时器任务前缀（区分每个句柄不一样的定时器）
    mv_u8_t   u8_stsk_num;                 ///< 固定事件定时器任务数（最少保留数量）
    mv_u8_t   u8_dtsk_num;                 ///< 动态事件定时器任务数（最多创建数量）
    mv_u32_t  u32_qinterval_ms;            ///< 轮询间隔（毫秒）
    mv_vptr_t phdl;                        ///< 初始化成功后的句柄入口
    mv_s32_t  s32_tsk_stacksize;           ///< 定时器任务栈大小（0=默认4*1024）
    mv_s32_t  s32_max_evt_inqueue;         ///< 最大待处理事件缓存数量（<=0默认为不限制；>0为限制数量，超额add返回异常)
}mvt_sevt_hdl_t;

/**
 * @brief 定时事件模块初始化
 * 
 * @param p [in] 初始化参数及输出模块句柄
 * @return 初始化结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS  (存在非法参数)
 *           : MV_EC_REDEF         (已初始化)
 *           : MV_EC_MALLOC_FAILED (内存申请失败)
 */
mv_s32_t mvt_sevt_init(mvt_sevt_hdl_t *p);
/**
 * @brief 添加一个事件
 * 
 * @param p                  [in] 已初始化的句柄
 * @param pitem              [in] 新的定时事件定义
 * @param s32_len            [in] 定义结构的长度（因为定义结构是变长结构体）
 * @param u32_first_delay_ms [in] 首次触发的延时时间（毫秒）
 * @return 添加结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS  (存在非法参数)
 *           : MV_EC_NOT_INIT      (句柄未初始化)
 *           : MV_EC_MALLOC_FAILED (内存申请失败)
 * @note: s32_len的三种入参用法
 * - >0 : 影子入参，item将会被完整拷贝一份内存到事件队列中（item修改与入参item无直接关系，多数是临时item）
 * - =0 : 实体入参，item将会直接在事件队列中引用（一般用于全局item，不需要释放内存）
 * - -1 : 实体入参，item将会直接在事件队列中引用，一般是临时申请的堆内存item（用到了变长结构特性），
          且不想像影子入参那样瞬时出现双份内存，会在事件结束后自动调用mvos_free释放（所以注意此方法的item需要是mvos_malloc匹配申请，避免不必要异常）
 */
mv_s32_t mvt_sevt_add_event(mvt_sevt_hdl_t *p, evt_item_t *pitem, mv_s32_t s32_len, mv_u32_t u32_first_delay_ms);
/**
 * @brief 移除一个指定名称的定时事件
 * 
 * @param p        [in] 已初始化的句柄
 * @param av8_name [in] 目标定时事件名称
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS  (存在非法参数)
 *           : MV_EC_NOT_INIT      (句柄未初始化)
 * @note 由于定时器本身存在异步行为，移除后极小几率存在触发一次的可能性（特别触发间隔较短的事件），请自行完善处理
 */
mv_s32_t mvt_sevt_del_event(mvt_sevt_hdl_t *p, mv_v8_t av8_name[16]);
/**
 * @brief 释放定时事件模块
 * 
 * @param p        [in] 已初始化的句柄
 * @return 操作结果 
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS  (存在非法参数)
 *           : MV_EC_NOT_INIT      (句柄未初始化)
 */
mv_s32_t mvt_sevt_uninit(mvt_sevt_hdl_t *p);

MVCXX_EXTERN_END

#endif
